package com.bluemoon.daps.test.sync.v1_3.devimport;

import cn.com.bluemoon.daps.common.enums.SyncToEnv;
import cn.com.bluemoon.daps.sync.DapsSyncApplication;
import cn.com.bluemoon.daps.sync.base.CompareResult;
import cn.com.bluemoon.daps.sync.base.DevModelCompareResult;
import cn.com.bluemoon.daps.sync.base.ModifyType.ModifyLevel;
import cn.com.bluemoon.daps.sync.core.sync.TableModel;
import cn.com.bluemoon.daps.sync.core.sync.compare.ModelCompareClient;
import cn.com.bluemoon.daps.sync.core.sync.compare.ModelCompareClient.BizType;
import cn.com.bluemoon.daps.sync.vo.dev2model.MetaTableOut;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.util.function.Tuple2;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Jarod.Kong
 * @date 2021/6/2 16:35
 */
@SpringBootTest(classes = DapsSyncApplication.class)
@RunWith(value = SpringRunner.class)
@Slf4j
public class Dev2ModelTestV2 extends BaseBefore {

    public Dev2ModelTestV2() {
        super(SyncToEnv.MODEL);
    }

    /**
     * 接口1
     */
    @Test
    public void test_model_dev_env_metadata_get_db_table_infos() {
        // 2021/5/31 需要元数据提供根据服务器信息获取数据库的表列表
        List<TableModel> metadataTableModel = getMetadataTableModel();
        // 考虑到前端需要勾选，返回id给后端，故以表英文名为id
        List<MetaTableOut> tables = metadataTableModel.stream().map(TableModel::getTable)
                .map(t-> {
                    MetaTableOut m = new MetaTableOut();
                    m.setId(t.getEngName());
                    m.setName(t.getEngName());
                    m.setNameZh(t.getName());
                    return m;
                }).collect(Collectors.toList());
        log.info("获取开发库表：{}", tables);
    }

    /**
     * 接口2
     */
    @Test
    public void test_dev2model_compare_selected_devtableId_to_compareModelTable() {
        String[] tbIds = {"dba_test_yzw", "test_tb_0", "test_tb_1"};
        HashSet<String> tableIds = new HashSet<>(Arrays.asList(tbIds));
        List<TableModel> metadataTables = getMetadataTableModel(tableIds);
        log.info("res={}", metadataTables);
    }

    /**
     * 接口3： 开发库导入模型-对比结果 + 基于所选的开发库表ok （部分库表vs模型表）
     */
    @Test
    public void test_dev2model_comare_result_by_selected_tablename() {
        String[] tbIds = {"dba_test_yzw", "test_tb_0", "test_tb_1"};
        Tuple2<List<TableModel>, List<TableModel>> localAndMetadataTableModel = getLocalAndMetadataTableModel(tbIds);
        List<TableModel> modelV1 = localAndMetadataTableModel.getT1();
        List<TableModel> modelV2 = localAndMetadataTableModel.getT2();
        globalConfig.setAddSink(false);
        // v1是模型（旧） v2是元数据（新）
        List<Map<ModifyLevel, List<CompareResult<DevModelCompareResult>>>> res3 =
                ModelCompareClient.doCompare(BizType.Dev2Model, globalConfig, modelV1, modelV2);
        // 去掉忽略的数据 然后返回给前端
        List<CompareResult<DevModelCompareResult>> res = getBizCompareResults(res3);
        log.info("导入开发库（对比结构）差异集：size:{}", res.size());
    }

    /**
     * 接口4：开发库导入模型-对比结果-对比入库 + 基于所选的开发库表ok （部分库表vs模型表）
     */
    @Test
    public void test_dev2model_comare_result_and_2model_by_selected_tablename() {
        String[] tbIds = {"dba_test_yzw", "test_tb_0", "test_tb_1"};
        Tuple2<List<TableModel>, List<TableModel>> localAndMetadataTableModel = getLocalAndMetadataTableModel(tbIds);
        List<TableModel> modelV1 = localAndMetadataTableModel.getT1();
        List<TableModel> modelV2 = localAndMetadataTableModel.getT2();
        globalConfig.setAddSink(true);
        List<Map<ModifyLevel, List<CompareResult<DevModelCompareResult>>>> res4 =
                ModelCompareClient.doCompare(BizType.Dev2Model, globalConfig, modelV1, modelV2);
        List<CompareResult<DevModelCompareResult>> res2 = getBizCompareResults(res4);
        log.info("导入开发库（对比结构）入库：size:{}", res2.size());
    }


    /**
     * 开发库导入模型-对比结果-对比入库 ok （全库表vs模型表）
     */
    @Test
    public void test_dev2model_comare_result_and_2model() {
        Tuple2<List<TableModel>, List<TableModel>> localAndMetadataTableModel = getLocalAndMetadataTableModel();
        doCompare0(localAndMetadataTableModel);
    }

    /**
     * 真正执行对比-开发库表同步模型
     *
     * @param localAndMetadataTableModel tuple2
     */
    public void doCompare0(Tuple2<List<TableModel>, List<TableModel>> localAndMetadataTableModel) {
        List<TableModel> modelV1 = localAndMetadataTableModel.getT1();
        List<TableModel> modelV2 = localAndMetadataTableModel.getT2();
        globalConfig.setAddSink(false);
        // v1是模型（旧） v2是元数据（新）
        List<Map<ModifyLevel, List<CompareResult<DevModelCompareResult>>>> res3 =
                ModelCompareClient.doCompare(BizType.Dev2Model, globalConfig, modelV1, modelV2);
        // 去掉忽略的数据 然后返回给前端
        List<CompareResult<DevModelCompareResult>> res = getBizCompareResults(res3);
        log.info("导入开发库（对比结构）差异集：size:{}", res.size());
        globalConfig.setAddSink(true);
        List<Map<ModifyLevel, List<CompareResult<DevModelCompareResult>>>> res4 =
                ModelCompareClient.doCompare(BizType.Dev2Model, globalConfig, modelV1, modelV2);
        List<CompareResult<DevModelCompareResult>> res2 = getBizCompareResults(res4);
        log.info("导入开发库（对比结构）入库：size:{}", res2.size());
    }

    /**
     * 只保留业务需要的变更数据
     *
     * @param res3 统一对比结果集
     * @return list
     */
    public List<CompareResult<DevModelCompareResult>> getBizCompareResults(List<Map<ModifyLevel, List<CompareResult<DevModelCompareResult>>>> res3) {
        List<CompareResult<DevModelCompareResult>> res = new ArrayList<>();
        for (Map<ModifyLevel, List<CompareResult<DevModelCompareResult>>> map : res3) {
            for (Map.Entry<ModifyLevel, List<CompareResult<DevModelCompareResult>>> entry : map.entrySet()) {
                List<CompareResult<DevModelCompareResult>> compareResults = entry.getValue().stream().filter(d -> !DevModelCompareResult.Action.Ignore.equals(d.getData().getAction())).collect(Collectors.toList());
                res.addAll(compareResults);
            }
        }
        return res;
    }


}
